﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;

namespace SilverAmp
{
    public interface ISongCollectionInfoProvider
    {
        /// <summary>
        /// Occurs after every song update in the collection
        /// </summary>
        event EventHandler SongUpdateCompleted;

        /// <summary>
        /// Occurs when the whole collection is updated
        /// </summary>
        event EventHandler SongCollectionUpdateCompleted;

        void UpdateSongs();
    }

    public class SongCollectionInfoProvider : ISongCollectionInfoProvider
    {
        /// <summary>
        /// Occurs after every song update in the collection
        /// </summary>
        public event EventHandler SongUpdateCompleted;

        private void InvokeSongUpdateCompleted()
        {
            EventHandler handler = SongUpdateCompleted;
            if (handler != null) handler(this, new EventArgs());
        }

        /// <summary>
        /// Occurs when the whole collection is updated
        /// </summary>
        public event EventHandler SongCollectionUpdateCompleted;

        private void InvokeSongCollectionUpdateCompleted()
        {
            EventHandler handler = SongCollectionUpdateCompleted;
            if (handler != null) handler(this,new EventArgs());
        }

        private readonly ObservableCollection<ITrackInfo> _songs;
        private readonly ISongInformationProvider _songInformationProvider;
        private Queue<ITrackInfo> songsToUpdate;

        public SongCollectionInfoProvider(ObservableCollection<ITrackInfo> songs, ISongInformationProvider songInformationProvider)
        {
            _songs = songs;
            _songInformationProvider = songInformationProvider;
        }
        BackgroundWorker bw = new BackgroundWorker();
        public void UpdateSongs()
        {
            //_songInformationProvider.SongDetailsUpdateComplete += new EventHandler<TrackEventArgs>(Done);

            //songsToUpdate = new Queue<ITrackInfo>(_songs);

            //if (songsToUpdate.Count > 0)
            //    _songInformationProvider.UpdateSongInformation(songsToUpdate.Dequeue());
            if (_songs == null) return;
            if (bw.IsBusy) return;
            bw.DoWork += new DoWorkEventHandler(bw_DoWork);
            bw.ProgressChanged += new ProgressChangedEventHandler(bw_ProgressChanged);
            bw.RunWorkerCompleted += delegate { InvokeSongCollectionUpdateCompleted(); };
            bw.WorkerReportsProgress = true;
            bw.RunWorkerAsync(_songs);
        }

        void bw_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            ITrackInfo t = e.UserState as ITrackInfo;
            int num =
                _songs.IndexOf(_songs.Where(s => s.Fileinfo.Name == t.Fileinfo.Name).First());
            try
            {
                _songs[num] = t;
            }catch(InvalidOperationException)
            {
                
            }
            InvokeSongUpdateCompleted();
        }

        void bw_DoWork(object sender, DoWorkEventArgs e)
        {
            
            ID3SongInformationProvider d = new ID3SongInformationProvider();
            ObservableCollection<ITrackInfo> songs =
                new ObservableCollection<ITrackInfo>(e.Argument as ObservableCollection<ITrackInfo>);
            double progressStep = 100/songs.Count;
            double progress = 0;
            foreach (var song in songs)
            {
                TrackInfo t = d.GetTrackInfo(song.Fileinfo);
               
                progress += progressStep;
                bw.ReportProgress((int)progress,t);
            }
        }

        private void Done(object sender, TrackEventArgs e)
        {
            int num =
                _songs.IndexOf(_songs.Where(s => s.Fileinfo.Name == e.TrackInfo.Fileinfo.Name).First());
            _songs[num] = e.TrackInfo;
            InvokeSongUpdateCompleted();
            if (songsToUpdate.Count > 0)
                _songInformationProvider.UpdateSongInformation(songsToUpdate.Dequeue());
            else
            {
                InvokeSongCollectionUpdateCompleted();
            }
        }
    }
}